import { parseDocument } from "htmlparser2";
import { compact, cloneDeep, assign } from "lodash-es";
import type { INode } from "./lib/types";
import { calcExp, calcFor, getTreeData } from "./utils/utils";


export class NodeParser {
    public nodeTree: INode[] = [];

    constructor(html: string) {
        const parser = parseDocument(html);
        this.nodeTree = parser.children.map(this.getNode.bind(this)).filter((node): node is INode => node !== undefined);
    }

    getNode(node: any): INode | undefined {
        const children = node.children ?? [];
        // 指令 v-for
        const vFor = node.attribs?.["v-for"] ?? "";
        // 指令 v-if
        const vIf = node.attribs?.["v-if"] ?? "";

        const condition: {
            type: string;
            value: string;
        }[] = [];

        if (vFor) {
            condition.push({ type: "v-for", value: vFor });
        }
        if (vIf) {
            condition.push({ type: "v-if", value: vIf });
        }

        // 先去除 Text 节点
        if (node.name === undefined && (node.data.trim() === "\n" || node.data.trim() === "")) {
            return undefined;
        }

        return assign(node, {
            tag: node.name,
            className: node?.attribs?.class ?? "",
            style: node?.attribs?.style ?? "",
            child: compact(children.map(this.getNode.bind(this))),
            isComponent: false,
            condition,
            data: node.data,
            display: true,
        });
    }
}


export class NodeRender {
    constructor(private node: INode) {

    }

    static valReg = /{{(.*?)}}/g;

    // 处理赋值
    private handleData(node: INode, inData: any, parent: INode): INode {
        // 处理节点 style data className 中使用到的变量
        if (node.data) {
            node.data = node.data.replace(NodeRender.valReg, (match, p1) => {
                console.log(p1,inData, "p1");
                return getTreeData(node, inData, p1);
            });
        }


        if (node.style) {
            node.style = node.style.replace(NodeRender.valReg, (match, p1) => {
                return getTreeData(node, inData, p1);
            });
        }

        if (node.className) {
            node.className = node.className.replace(NodeRender.valReg, (match, p1) => {
                return getTreeData(node, inData, p1);
            });
        }
        

        if (node.child.length > 0) {
            node.child.forEach((child) => {
                this.handleData(child, inData, node);
            });
        }

        return node;
    }

    private handleLogic(node: INode, inData: any, parent: INode): INode {
        // 处理节点 v-if
        if (node.condition) {
            node.condition.forEach((condition) => {
                if (condition.type === "v-for") {
                    const vals = calcFor(condition.value, inData, node);
                    console.log(node.localData, vals, "vals");
                    // 需要对数据进行处理
                    parent.child = vals.map((val) => {
                        node.condition = [];
                        // 需要cloneDeep 因为 数据是引用类型
                        return cloneDeep(node)
                    });

                    parent.child.forEach((child, index) => {
                        for (let i = 0; i < child.child.length; i++) {
                            child.child[i].localData = assign(child.child[i].localData, cloneDeep(vals[index][i]));
                        }
                        child.localData = assign(child.localData, cloneDeep(vals[index]));
                    });
                }

                if (condition.type === "v-if") {
                    const judge = calcExp(condition.value, inData, node);
                    if (!judge) {
                        node.display = false;
                    }
                }
            });
        }

       
        if (node.child.length > 0) {
            node.child.forEach((child) => {
                this.handleLogic(child, inData, node);
            });
        }
     
        return node;
    }

    private handleChildren(node: INode, inData: any) {
        // 处理逻辑
        node = this.handleLogic(node, inData, node);
        // 处理赋值
        this.handleData(node, inData, node);
    }

    render(inData: any) {
        const node = this.node;
       
        console.time("render");
        this.handleChildren(node, inData);
        // // 需要解决 数据问题
        this.handleChildren(node, inData);
        console.timeEnd("render");
        return node;
    }
}

